package cn.lg.soar.core.aspect;

import cn.lg.soar.common.util.current.ICurrentUser;
import cn.lg.soar.common.util.current.UserContext;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.context.ApplicationContext;
import org.springframework.context.expression.MethodBasedEvaluationContext;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.core.ParameterNameDiscoverer;

/**
 * aop spel 支持
 * @author luguoxiang
 * @date 2021/9/25
 * 开源项目：https://gitee.com/lgx1992/lg-soar 求star！请给我star！请帮我点个star！
 */
public class AopEvaluationContext extends MethodBasedEvaluationContext {

    public final static String APPLICATION_CONTEXT = "$";
    public final static String CURRENT_USERNAME = "@n";
    public final static String CURRENT_USERID = "$u";
    public final static String CURRENT_USERTYPE = "$ut";
    public final static String CURRENT_TENANTID = "$t";
    public final static String CURRENT_TIME_MILLIS = "$ts";
    public final static String RESULT = "$r";

    private static final ParameterNameDiscoverer PARAMETER_NAME_DISCOVERER = new DefaultParameterNameDiscoverer();

    public AopEvaluationContext(JoinPoint point, ApplicationContext applicationContext, Object result) {
        super(
                null,
                ((MethodSignature) point.getSignature()).getMethod(),
                point.getArgs(),
                AopEvaluationContext.PARAMETER_NAME_DISCOVERER
        );
        ICurrentUser currentUser = UserContext.getUserNullable();
        if (currentUser != null) {
            this.setVariable(CURRENT_USERNAME, currentUser.getUsername());
            this.setVariable(CURRENT_USERID, currentUser.getId());
            this.setVariable(CURRENT_USERTYPE, currentUser.getUserType());
            this.setVariable(CURRENT_TENANTID, currentUser.getCurrentTenantId());
        }
        this.setVariable(APPLICATION_CONTEXT, applicationContext);
        this.setVariable(CURRENT_TIME_MILLIS, System.currentTimeMillis());
        this.setVariable(RESULT, result);
    }

    public AopEvaluationContext(JoinPoint point, ApplicationContext applicationContext) {
        this(point, applicationContext, null);
    }

    public AopEvaluationContext(Object rootObject, JoinPoint point) {
        super(
                rootObject,
                ((MethodSignature) point.getSignature()).getMethod(),
                point.getArgs(),
                AopEvaluationContext.PARAMETER_NAME_DISCOVERER
        );
    }

    public AopEvaluationContext(JoinPoint point) {
        super(
                null,
                ((MethodSignature) point.getSignature()).getMethod(),
                point.getArgs(),
                AopEvaluationContext.PARAMETER_NAME_DISCOVERER
        );
    }

}
